import java.io.Serializable;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class AssociativeBloomFilter<E> {

    private BloomFilter filter;

    private static int MAX_COUNT = Integer.MAX_VALUE;

    private int size;

    public AssociativeBloomFilter(double c, int n, int k) {
      this.filter = new BloomFilter(c,n,k);
      this.size = 0;
    }

    public AssociativeBloomFilter(int bitSetSize, int expectedNumberOfElements) {
      this.filter = new BloomFilter(bitSetSize,expectedNumberOfElements);
      this.size = 0;
    }

    public AssociativeBloomFilter(double falsePositiveProbability, int expectedNumberOfElements) {
      this.filter = new BloomFilter(falsePositiveProbability,expectedNumberOfElements);
      this.size = 0;
    }

    public AssociativeBloomFilter(int bitSetSize, int expectedNumberOfFilterElements, int actualNumberOfFilterElements, BitSet filterData) {
      this.filter = new BloomFilter(bitSetSize, expectedNumberOfFilterElements, actualNumberOfFilterElements);
      this.size = 0;
    }

    public void put ( E key, Integer value ) {
	int i = 1;
	for ( ; i < MAX_COUNT && i < value ; i++ ) if ( !filter.contains(key.toString() + i) ) break;
	for ( ; i < MAX_COUNT && i < value ; i++ ) filter.add(key.toString() + (i));
	if ( i == 1 ) size++;
    }

    public void increment ( E key ) {
	int i = 1;
	for ( ; i < MAX_COUNT ; i++ ) if ( !filter.contains(key.toString() + i) ) break;
	filter.add(key.toString() + (i));
	if ( i == 1 ) size++;
    }

    public Integer get ( E key ) {
	for ( int i = 0 ; i < MAX_COUNT ; i++ ) if ( !filter.contains(key.toString() + (i+1)) ) return i;
	return 0;
    }

    public boolean isEmpty() { return size == 0; }

    public int size() { return size; }

}
